#include "path_pool.hh"
#include <functional>
#include "thirdparty/kconfig/interface/config.h"

namespace kratos { namespace engine {

PathPool::PathPool(EngineImpl* engine)
    : maxCnt_(1), engine_(engine) {
}

PathPool::~PathPool() {
}

bool PathPool::start(kconfig::Config * config) {
    if (config->has("gateway.pathPoolMax")) {
        maxCnt_ = config->getInt32("gateway.pathPoolMax");
    }
    return true;
}

bool PathPool::addPath(SiteType siteType, PathID pathID) {
    auto& pathInfo = sitePathMap_[siteType];
    auto& siteID = engine_->getPathPeerSiteID(pathID);
    siteIDPathMap_[siteID.u64()] = pathID;
    pathInfo.pathList.emplace_back(pathID);
    return true;
}

void PathPool::removePath(SiteType siteType, PathID pathID) {
    auto& pathInfo = sitePathMap_[siteType];
    auto it = std::find(pathInfo.pathList.begin(), pathInfo.pathList.end(), pathID);
    if (it == pathInfo.pathList.end()) {
        return;
    }
    auto& siteID = engine_->getPathPeerSiteID(pathID);
    siteIDPathMap_.erase(siteID);
    pathInfo.pathList.erase(it);
}

PathID PathPool::getPath(SiteType siteType, UserData userData) {
    auto& pathInfo = sitePathMap_[siteType];
    if (pathInfo.pathList.size() < (std::size_t)maxCnt_) {
        if (!engine_->internalFindPath(siteType, userData)) {
            logecom("PathPool") << "Query path failed for site type:" << siteType << logend;
            return INVALID_PATH_ID;
        } else {
            return INVALID_PATH_ID;
        }
    }
    return selectPath(pathInfo);
}

PathID PathPool::getPath(const grid::SiteID & siteID, UserData userData) {
    auto it = siteIDPathMap_.find(siteID.u64());
    if (it == siteIDPathMap_.end()) {
        if (!engine_->internalFindPath(siteID, userData)) {
            logecom("PathPool") << "Query path failed for site ID:" << siteID.toString() << logend;
            return INVALID_PATH_ID;
        }
        return INVALID_PATH_ID;
    }
    return it->second;
}

PathID PathPool::selectPath(PathInfo & pathInfo) {
    if (pathInfo.pathList.empty()) {
        return INVALID_PATH_ID;
    }
    auto& pathList = pathInfo.pathList;
    if (pathInfo.roundIndex >= pathList.size()) {
        pathInfo.roundIndex = 0;
    }
    return pathList[pathInfo.roundIndex++];
}

}}
